/*
 * temperature.cpp
 *
 *  Created on: 23/02/2013
 *      Author: cerber0
 */
#include <temperature.h>

dht DHT11;

const int sensorDeepth = 10;
int soilHistory[sensorDeepth];
int photocellHistory[sensorDeepth];
int thermistorHistory[sensorDeepth];

//Celsius to Fahrenheit conversion
double temperature::Fahrenheit(double celsius)
{
	return 1.8 * celsius + 32;
}

// fast integer version with rounding
//int Celcius2Fahrenheit(int celcius)
//{
//  return (celsius * 18 + 5)/10 + 32;
//}
double temperature::ntc2celsius(double value)
{
	float Vin = 5.0;     // [V]       Tensión alimentación del divisor
	float Rfija = 12000;  // [ohm]     Resistencia fija del divisor
	float R25 = 150000;    // [ohm]     Valor de NTC a 25ºC
	float Beta = 4370.0; // [K]      Parámetro Beta de NTC
	float T0 = 298.15;   // [K]       Temperatura de referencia en Kelvin

	float Vout = 0.0;    // [V]       Variable para almacenar Vout
	float Rntc = 0.0;    // [ohm]     Variable para NTC en ohmnios

	float TempK = 0.0;   // [K]       Temperatura salida en Kelvin
	float TempC = 0.0;   // [ºC]      Temperatura salida en Celsius

	//Primero la Vout del divisor
	Vout=(Vin/1024)*value;

	//Ahora la resistencia de la NTC
	Rntc=(Vout*Rfija)/(Vin-Vout);

	//Y por último la temperatura en Kelvin
	TempK = Beta/(log(Rntc/R25)+(Beta/T0));

	//Y ahora la pasamos a celsius
	TempC = TempK-273.15;
	return TempC;

}

//Celsius to Kelvin conversion
double temperature::Kelvin(double celsius)
{
	return celsius + 273.15;
}

// dewPoint function NOAA
// reference: http://wahiduddin.net/calc/density_algorithms.htm
double temperature::dewPoint(double celsius, double humidity)
{
	double A0= 373.15/(273.15 + celsius);
	double SUM = -7.90298 * (A0-1);
	SUM += 5.02808 * log10(A0);
	SUM += -1.3816e-7 * (pow(10, (11.344*(1-1/A0)))-1) ;
	SUM += 8.1328e-3 * (pow(10,(-3.49149*(A0-1)))-1) ;
	SUM += log10(1013.246);
	double VP = pow(10, SUM-3) * humidity;
	double T = log(VP/0.61078);   // temp var
	return (241.88 * T) / (17.558-T);
}

// delta max = 0.6544 wrt dewPoint()
// 5x faster than dewPoint()
// reference: http://en.wikipedia.org/wiki/Dew_point
double temperature::dewPointFast(double celsius, double humidity)
{
	double a = 17.271;
	double b = 237.7;
	double temp = (a * celsius) / (b + celsius) + log(humidity/100);
	double Td = (b * temp) / (a - temp);
	return Td;
}


void temperature::calibration()
{
	int reading;
	soilMin = 1023;
	soilMax = 0;
	// calibrate during the first five seconds
	//Serial.print(millis());
	//Serial.print(" ,\t");
	while (millis() < 10000) {
		reading = analogRead(SOIL_PIN);
		//Serial.print("sensor inicio=> ");
		//Serial.println(reading);
		// record the maximum sensor value
		if (reading > soilMax) {
			soilMax = reading;
		}

		// record the minimum sensor value
		if (reading < soilMin) {
			soilMin = reading;
		}
		//Serial.print(soilMin);
		//Serial.print(" ,\t");
		//Serial.print(soilMax);
		//Serial.print(" ,\t");
	}
}

void temperature::readSoil()
{
	long soil_read = 0, soil_now;

	soil_read = analogRead(SOIL_PIN);

	soil_now = soil_read;

	for (int i = sensorDeepth-1; i > 0; i--)
	{
		soilHistory[i] = soilHistory[i-1];
		soil_read += soilHistory[i];
	}

	soilHistory[0] = soil_now;

	soilHumidity = (double) soil_read*100/(1024*sensorDeepth);
}





int temperature::read()
{
	int chk = DHT11.read11(DHT11_PIN);
	long soil_read = 0, soil_now;
	long temp_read = 0, temp_now;
	long photo_read = 0, photo_now;

	temp_read = analogRead(THER_PIN);
	photo_read = analogRead(PHOTO_PIN);

	temp_now = temp_read;
	photo_now = photo_read;

	for (int i = sensorDeepth-1; i > 0; i--)
	{
		photocellHistory[i] = photocellHistory[i-1];
		photo_read += photocellHistory[i];

		thermistorHistory[i] = thermistorHistory[i-1];
		temp_read += thermistorHistory[i];
	}

	photocellHistory[0] = photo_now;
	thermistorHistory[0] = temp_now;

	thermistor = (double) 500*(1024-temp_read)/(1024*sensorDeepth)+2;

	photocell = (float) photo_read*5/(sensorDeepth*1024);

	switch (chk)
	{
	case DHTLIB_OK:
		//Serial.print("OK,\t");
		dewPointD = dewPoint(DHT11.temperature,DHT11.humidity);
		temp = DHT11.temperature;
		humidity = DHT11.humidity;
		break;
	case DHTLIB_ERROR_CHECKSUM:
		//Serial.print("Checksum error,\t");
		break;
	case DHTLIB_ERROR_TIMEOUT:
		//Serial.print("Time out error,\t");
		break;
	default:
		//Serial.print("Unknown error,\t");
		break;
	}
	return chk;
}

int temperature::readAll()
{
	long soil_read = 0, soil_now;
	long temp_read = 0, temp_now;
	long photo_read = 0, photo_now;

	temp_read = analogRead(THER_PIN);
	photo_read = analogRead(PHOTO_PIN);
	soil_read = analogRead(SOIL_PIN);

	soil_now = soil_read;
	temp_now = temp_read;
	photo_now = photo_read;

	for (int i = sensorDeepth-1; i > 0; i--)
	{
		soilHistory[i] = soilHistory[i-1];
		soil_read += soilHistory[i];

		photocellHistory[i] = photocellHistory[i-1];
		photo_read += photocellHistory[i];

		thermistorHistory[i] = thermistorHistory[i-1];
		temp_read += thermistorHistory[i];
	}

	photocellHistory[0] = photo_now;
	thermistorHistory[0] = temp_now;
	soilHistory[0] = soil_now;

	soilHumidity = (double) soil_read*100/(1024*sensorDeepth);

	thermistor = (double) 500*(temp_read)/(1024*sensorDeepth)+2;

	photocell = (float) photo_read*5/(sensorDeepth*1024);
//Serial.println((double)500*temp_now/1024+2,3);

	int chk = DHT11.read11(DHT11_PIN);

	switch (chk)
	{
	case DHTLIB_OK:
		//Serial.print("OK,\t");
		dewPointD = dewPoint(DHT11.temperature,DHT11.humidity);
		temp = DHT11.temperature;
		humidity = DHT11.humidity;
		break;
	case DHTLIB_ERROR_CHECKSUM:
		//Serial.print("Checksum error,\t");
		break;
	case DHTLIB_ERROR_TIMEOUT:
		//Serial.print("Time out error,\t");
		break;
	default:
		//Serial.print("Unknown error,\t");
		break;
	}
	return chk;
}


